﻿using MessagePack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using Umi.Crypto.Abstraction.Keys;
using Umi.Web.Metadatas.Attributes;

namespace Umi.Web.Crypto.HMacs
{
    [Service("PBKDF2KeyCreator", Scoped = ServiceScoped.Single)]
    public class PBKDF2KeyFactory : IKeyParameterCreator
    {
        private readonly ILogger logger;

        private readonly IConfiguration _configuration;

        public PBKDF2KeyFactory(ILogger<PBKDF2KeyFactory> logger, IConfiguration configuration)
        {
            this.logger = logger;
            _configuration = configuration;
        }

        public KeyParameter Create(string key)
        {
            logger.LogDebug(key);
            logger.LogDebug("开始解析Key");
            string[] format = key.Split(',');
            return new PBKDF2KeyParameter(
                Convert.ToInt32(format[0]),
                Convert.FromBase64String(format[1]),
                Convert.FromBase64String(format[2]),
                Convert.ToInt32(format[3]));
        }

        public KeyParameter RandomKey()
        {
            int dkLen = _configuration.GetValue<int>("Secret:PBKDF2:DKLen");
            int count = _configuration.GetValue<int>("Secret:PBKDF2:Count");
            RandomNumberGenerator rnd = RandomNumberGenerator.Create();
            byte[] key = new byte[24];
            byte[] salt = new byte[24];
            rnd.GetBytes(key);
            rnd.GetBytes(salt);
            return new PBKDF2KeyParameter(dkLen, key, salt, count);

        }
    }

    public class PBKDF2KeyParameter : KeyParameter
    {
        public int DkLen { get; }

        public byte[] Key { get; }

        public byte[] Salt { get; }

        public int Count { get; }

        public PBKDF2KeyParameter(int dkLen, byte[] key, byte[] salt, int count)
        {
            DkLen = dkLen;
            Key = key;
            Salt = salt;
            Count = count;
        }

        public override string ToString()
        {
            return $"{DkLen},{Convert.ToBase64String(Key)},{Convert.ToBase64String(Salt)},{Count}";
        }
    }
}
